﻿using LeRenard;
using LeRenard.Core.Numbers;
using LeRenard.Core.Time;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;

namespace LeRenard.Core.Tests._core_._extensions_
{
    public class IRangeExtensionsTests
    {
        #region IRange<int>
        [Fact]
        public void IRangeInt_AsEnumerable_Returns_All_Elements()
        {
            // Arrange
            var range = new Int32Range(0, 9);
            var expected = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            // Act
            var actual = range.AsEnumerable();

            // Assert
            Assert.Equal(expected.Count, actual.Count());
            Assert.Equal(expected, actual);
        }
        #endregion

        #region IRange<DateTime>
        [Fact]
        public void IRangeDateTime_GetWeekdays_Returns_Weekdays()
        {
            // Arrange
            var range = new DateTimeRange(
                new DateTime(2014, 06, 16), // monday
                new DateTime(2014, 06, 22) // sunday
            );
            var expected = new List<DateTime>() {
                new DateTime(2014, 06, 16),
                new DateTime(2014, 06, 17),
                new DateTime(2014, 06, 18),
                new DateTime(2014, 06, 19),
                new DateTime(2014, 06, 20),
            };

            // Act
            var actual = range.GetWeekdays();

            // Assert
            Assert.Equal(expected.Count, actual.Count());
            Assert.Equal(expected, actual);
        }

        [Fact]
        public void IRangeDateTime_GetWeekendDays_Returns_WeekendDays()
        {
            // Arrange
            var range = new DateTimeRange(
                new DateTime(2014, 06, 16), // monday
                new DateTime(2014, 06, 22) // sunday
            );
            var expected = new List<DateTime>() {
                new DateTime(2014, 06, 21),
                new DateTime(2014, 06, 22)
            };

            // Act
            var actual = range.GetWeekendDays();

            // Assert
            Assert.Equal(expected.Count, actual.Count());
            Assert.Equal(expected, actual);
        }

        [Fact]
        public void IRangeDateTime_GetDays_DayOfWeek_Returns_Correct_Days()
        {
            // Arrange
            var range = new DateTimeRange(
                new DateTime(2014, 06, 01),
                new DateTime(2014, 06, 30)
            );
            var expected = new List<DateTime>() {
                new DateTime(2014, 06, 2),
                new DateTime(2014, 06, 9),
                new DateTime(2014, 06, 16),
                new DateTime(2014, 06, 23),
                new DateTime(2014, 06, 30)
            };

            // Act
            var actual = range.GetDays(DayOfWeek.Monday);

            // Assert
            Assert.Equal(expected.Count, actual.Count());
            Assert.Equal(expected, actual);
        }

        [Fact]
        public void IRangeDateTime_GetDays_DaysOfWeek_Returns_Correct_Days()
        {
            // Arrange
            var range = new DateTimeRange(
                new DateTime(2014, 06, 01),
                new DateTime(2014, 06, 30)
            );
            var daysOfWeek = new List<DayOfWeek>() {
                DayOfWeek.Monday, DayOfWeek.Wednesday
            };
            var expected = new List<DateTime>() {
                new DateTime(2014, 06, 2), new DateTime(2014, 06, 4),
                new DateTime(2014, 06, 9), new DateTime(2014, 06, 11),
                new DateTime(2014, 06, 16), new DateTime(2014, 06, 18),
                new DateTime(2014, 06, 23), new DateTime(2014, 06, 25),
                new DateTime(2014, 06, 30)
            };

            // Act
            var actual = range.GetDays(daysOfWeek);

            // Assert
            Assert.Equal(expected.Count, actual.Count());
            Assert.Equal(expected, actual);
        }

        [Fact]
        public void IRangeDateTime_GetDays_Func_Returns_Correct_Days()
        {
            // Arrange
            var range = new DateTimeRange(
                new DateTime(2014, 01, 01),
                new DateTime(2014, 12, 31)
            );
            var expected = new List<DateTime>() {
                new DateTime(2014, 01, 01), new DateTime(2014, 02, 01),
                new DateTime(2014, 03, 01), new DateTime(2014, 04, 01),
                new DateTime(2014, 05, 01), new DateTime(2014, 06, 01),
                new DateTime(2014, 07, 01), new DateTime(2014, 08, 01),
                new DateTime(2014, 09, 01), new DateTime(2014, 10, 01),
                new DateTime(2014, 11, 01), new DateTime(2014, 12, 01),
            };

            // Act
            var actual = range.GetDays(d => d.Day.Equals(1));

            // Assert
            Assert.Equal(expected.Count, actual.Count());
            Assert.Equal(expected, actual);
        }

        [Fact]
        public void IRangeDateTime_GetDays_Returns_Correct_Days()
        {
            // Arrange
            var range = new DateTimeRange(
                new DateTime(2014, 01, 01),
                new DateTime(2014, 01, 07)
            );
            var expected = new List<DateTime>() {
                new DateTime(2014, 01, 01),
                new DateTime(2014, 01, 02),
                new DateTime(2014, 01, 03),
                new DateTime(2014, 01, 04),
                new DateTime(2014, 01, 05),
                new DateTime(2014, 01, 06),
                new DateTime(2014, 01, 07)
            };

            // Act
            var actual = range.GetDays();

            // Assert
            Assert.Equal(expected.Count, actual.Count());
            Assert.Equal(expected, actual);
        }
        #endregion
    }
}
